package cn.monkey.data.entity.datascope;

import cn.monkey.data.entity.UserSession;
import cn.monkey.data.entity.dto.ExtensionQueryRequest;
import org.springframework.util.CollectionUtils;

import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.function.Predicate;

public class SimpleDatascopeDefinitionPredicateFactory implements DatascopeDefinitionPredicateFactory {

    private final DatascopeDefinitionPredicateFactory predicateFactory;

    public SimpleDatascopeDefinitionPredicateFactory(DatascopeDefinitionPredicateFactory predicateFactory) {
        this.predicateFactory = new IterableDatascopeDefinitionPredicateFactory(this);
    }

    @Override
    public Predicate<ExtensionQueryRequest> apply(DatascopeDefinition datascopeDefinition) {
        String type = datascopeDefinition.getType();
        String rid = datascopeDefinition.getRid();
        Predicate<ExtensionQueryRequest> p = extensionQueryRequest -> {
            if (DatascopeType.ALL.getCode().equals(type)) {
                return true;
            }
            String uid = extensionQueryRequest.getUid();
            if (DatascopeType.PERSONAL.getCode().equals(type)) {
                if (uid.equals(rid)) {
                    return true;
                }
            }
            UserSession userSession = extensionQueryRequest.getUserSession();
            if (userSession == null) {
                return false;
            }
            Map<String, Collection<String>> groupMap = userSession.getGroupMap();
            if (CollectionUtils.isEmpty(groupMap)) {
                return false;
            }
            if (DatascopeType.PARTITION.getCode().equals(type)) {
                Collection<String> deptIds = groupMap.values()
                        .stream().reduce((l1, l2) -> {
                            HashSet<String> set = new HashSet<>(l1);
                            set.addAll(l2);
                            return set;
                        })
                        .orElse(Collections.emptySet());
                return deptIds.contains(rid);
            }
            if (DatascopeType.GROUP.getCode().equals(type)) {
                return groupMap.containsKey(rid);
            }
            return false;
        };
        return p.and(this.predicateFactory.apply(datascopeDefinition));
    }
}
